using System.Security.Cryptography;
using System.Text;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
using Yukisky.CommonUtils;

namespace Yukisky.IdentifyUser
{
    public class Utils
    {
        public static string Md5Sum(string input)
        {
            var md5 = new MD5CryptoServiceProvider();
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); 
            byte[] hash = md5.ComputeHash(inputBytes); 
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("X2"));
            } 
            return sb.ToString();
        }
        
        public static int CalculateAge(int year , int month , int day , int y, int m , int d)
        {
            int age = year - y - 1; //不计算当年
            if (month > m || (month == m && day > d) ) //月大于 或者 当月的日大于
            {
                age++;
            }
            return age;
        }

        public static DateTime GetTime()
        {
            // var data = DateTime.UtcNow.AddHours(8);
            // var timeService = GGServices.GetTimerService();
            // if (!timeService.isDirty)
            // {
            //     data = data.AddSeconds(timeService.RemoteLocalTimeDelta);
            // }
            //
            // return data;
            return IdentifyMgr.GetTimeServices().GetNowTime();
        }
        /// <summary>
        /// 是否是节假日
        /// </summary>
        static Dictionary<string, bool> HolidayCached = new Dictionary<string, bool>();
        /// <summary>
        /// 
        /// </summary>
        static Dictionary<string, int> TimeCached = new Dictionary<string, int>();
        
        static void IsHoliday( string day, Action<bool,bool> callback )
        {
           
            if (HolidayCached.ContainsKey(day))
            {
                callback(true,HolidayCached[day]);
            }
            else
            {
                UnityMainThreadDispatcher.Instance().Enqueue(RequestHoliday(day,callback));
            }
        }

        class HolidayType
        {
            public int type;
            public string name;
            public int week;
        }
        class HolidayInfo
        {
            public int code;
            public HolidayType type;
        }

        public static IEnumerator RequestHoliday(string day , Action<bool,bool> callback)
        {
            var req = UnityWebRequest.Get("https://timor.tech/api/holiday/info/" + day);
            req.SetRequestHeader("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36");
            req.timeout = 10;
            yield return req.SendWebRequest();
            if (req.isHttpError || req.isNetworkError)
            {
                callback(false,false);
            }
            else
            {
                if (req.responseCode == 200)
                {
                    var info = JsonConvert.DeserializeObject<HolidayInfo>(req.downloadHandler.text);
                    if (info.code == 0 )
                    {
                        //0 工作日 1 周末 2 假期 3 调休 (1,2或者周五) 可玩
                        HolidayCached.Add(day,info.type.type == 1 || info.type.type == 2 || info.type.week == 5);
                        callback(true,HolidayCached[day]);
                    }
                    else
                    {
                        callback(false,false);
                    }
                }
                else
                {
                    callback(false,false);
                }
            }
        }

        public static bool GetBirthdayFromIDNum(string number , ref IdentifyResult identifyResult)
        {
            string birthday = String.Empty;
            bool success = false;
            //验证身份证
            if (Regex.IsMatch(number, "^\\d{15}$"))
            {
                //一代
                int y = int.Parse(number.Substring(6, 2)) +1900;
                int m = int.Parse(number.Substring(8, 2)) ;
                int d = int.Parse(number.Substring(10, 2)) ;
                //默认19开头
                //age = CalculateAge(year, month, day, y, m, d);
                birthday = $"{y}.{m}.{d}";
                if (CheckYear(y,m,d))
                {
                    success = true;
                    if (identifyResult != null)
                    {
                        identifyResult.Birthday = birthday;
                    }
                }
                else
                {
                    Debug.LogWarning("身份证年份错误");
                }
            }else if (Regex.IsMatch(number, "^\\d{18}|\\d{17}[X]$"))
            {
                //2代
                int y = int.Parse(number.Substring(6, 4)) ;
                int m = int.Parse(number.Substring(10, 2)) ;
                int d = int.Parse(number.Substring(12, 2)) ;
                //age = CalculateAge(year, month, day, y, m, d);
                birthday = $"{y}.{m}.{d}";
                if (CheckYear(y, m, d))
                {
                    success = true;
                    identifyResult.Birthday = birthday;
                }
                else
                {
                    Debug.LogWarning("身份证年份错误");
                }
            }
            else
            {
                Debug.LogWarning("身份证正则表达式错误");
                //Debug.Log("身份证验证失败");
            }

            return success;
        }
        
        private static bool CheckYear(int y , int m , int d)
        {
            if (y <= 1850 )
            {
                return false;
            }

            if (!maxDay.ContainsKey(m))
            {
                return false;
            }

            if (d <= 0 || d> 31)
            {
                return false;
            }

            int max = maxDay[m];
            if (d > max)
            {
                if (d == 29 && m == 2 && run(y))
                {
                    return true;
                }
                return false;
            }

            return true;
        }
        /// <summary>
        /// 闰年
        /// </summary>
        /// <param name="y"></param>
        /// <returns></returns>
        private static bool run(int y)
        {
            if (y % 100 != 0)
            {
                return y % 4 == 0;
            }
            else
            {
                return y % 400 == 0;
            }
        }
        
        private static Dictionary<int, int> maxDay = new Dictionary<int, int>
        {
            {1, 31},
            {2, 28},
            {3, 31},
            {4, 30},
            {5, 31},
            {6, 30},
            {7, 31},
            {8, 31},
            {9, 30},
            {10, 31},
            {11, 30},
            {12, 31},
            
        };
        
        

        private static List<int> _timeLimit = new List<int> {90, 180};
        /// <summary>
        /// 
        /// </summary>
        /// <param name="minutes"></param>
        /// <param name="action"> <是否超过了时间,超过的原因> 0.查询节假日失败,1.非节假日,2.不在8点到9点之间</param>
        public static void CheckTime(int minutes, Action<bool,int> action)
        {
            var time = GetTime();
            var day = $"{time.Year}-{time.Month}-{time.Day}";

            if (time.Hour >= 21 || time.Hour < 20)
            {
                //该时间段一律不允许
                action(  true  ,2);
                return;
            }
            
            
            // if (TimeCached.ContainsKey(day))
            // {
            //     action(  minutes >= TimeCached[day]  ,(TimeCached[day] == _timeLimit[0])? 0:1);
            // }
            // else
            // {
            IsHoliday(day,(s,b) => 
            {
                if (s)
                {
                    //非节假日才可以正常玩
                    action(b == false, 1);
                    // TimeCached.Add(day,b?_timeLimit[1]:_timeLimit[0]);
                    // action(  minutes >= TimeCached[day]  ,(TimeCached[day] == _timeLimit[0])?  0:1);
                }
                else
                {
                    action(true, 0);
                    //action(  minutes >= _timeLimit[0]  ,0);
                }
                
            });
            //}
            
        }
    }
}